﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using ShkSimulation.carsharing;
using ShkSimulation.core.template;
using ShkSimulation.core.template.agency;
using ShkSimulation.desktop.component.tools;
using ShkSimulation.carsharing.impl;
using ShkSimulation.carsharing.impl.elements;

namespace ShkSimulation.desktop.component {
	
    public sealed partial class NetworkShowControl : UserControl, ResetSimulation {

	    public event Action<Station> OnStationClick; 
	    
	    public event Action<Road> OnRoadClick; 
	    
	    public event Action<Network> OnNetworkClick; 
	    
        public NetworkShowControl() {
            InitializeComponent();
            this.Dock = DockStyle.Fill;
        }
        
        private SimulationApplication application;
		private Network network;
		private NetworkResultHolder ResultHolder { get; set; }
		private NetworkEnvironment NetworkInputData { get; set; }
		private Dictionary<Station, StationControl> Stations { get; set; }
		private Dictionary<Road, RoadControl> Roads { get; set; }

		public void SetSimulationApplication(SimulationApplication app) {
			Reset();
			this.application = app;
			application.AfterInitSuccess += this.AfterInitialize;
		}
		
		public void Reset() {
			OnStationClick = null;
			OnRoadClick = null;
			OnNetworkClick = null;
			this.Stations = new Dictionary<Station, StationControl>();
			this.Roads = new Dictionary<Road, RoadControl>();
			this.MainControlPanel.Controls.Clear();
		}
		
		public void AfterInitialize(SimulationInfo simulationInfo) {
			this.network = application.SimulationNetwork;
			this.NetworkInputData = application.NetworkInputData;
			this.ResultHolder = application.ResultHolder;
			this.BeginInvoke(new Action(() => {
				PaintItems();
			}));
		}

		private void PaintItems() {
			if (NetworkInputData != null) {
				MainControlPanel.Controls.Clear();
				Stations = new Dictionary<Station, StationControl>();
				Roads = new Dictionary<Road, RoadControl>();
				var dictionary = PaintStation(new List<Agency>(NetworkInputData.ClassifiedAgencies[CarsharingConfig.StationResourceKey]));
				PaintRoad(new List<Agency>(NetworkInputData.ClassifiedAgencies[CarsharingConfig.RoadResourceKey]), dictionary);
				foreach (var (station, stationControl) in Stations) {
					stationControl.Click += (_, _) => {
						SetSelectedControl(stationControl);
						if (OnStationClick != null) OnStationClick(station);
					};
				}
				foreach (var (road, roadControl) in Roads) {
					roadControl.Click += (_, _) => {
						SetSelectedControl(roadControl);
						if (OnRoadClick != null) OnRoadClick(road);
					};
				}
			}
		}
		
		private Control SelectedControl;
		
		private void SetSelectedControl(Control control) {
			if (control == SelectedControl) {
				return;
			}
			if (SelectedControl != null) {
				if (SelectedControl is RoadControl roadControl) {
					roadControl.ResetColor();
				}else if (SelectedControl is StationControl stationConfigControl) {
					stationConfigControl.ResetColor();
				}
			}
			if (control is RoadControl roadConfigControl) {
				roadConfigControl.RoadColor = Color.Tomato;
				SelectedControl = roadConfigControl;
			}else if (control is StationControl stationConfigControl) {
				stationConfigControl.BackColor = Color.Tomato;
				SelectedControl = stationConfigControl;
			}
		}

		private Dictionary<Station, Point> PaintStation(List<Agency> stations) {
			if (stations == null || stations.Count == 0) {
				return new Dictionary<Station, Point>();
			}
			int width = MainControlPanel.Width;
			int height = MainControlPanel.Height;
			Point center = new Point(width / 2, height / 2);
			int size = Math.Min(width, height) / 8;
			int axisLength = Math.Min(width, height) / 2 - size;
			List<Point> points = GetPoints(center, axisLength, stations.Count);
			Dictionary<Station, Point> stationDictionary = new Dictionary<Station, Point>();
			for (int i = 0; i < points.Count; i++) {
				Station station = stations[i] as Station;
				StationControl stationControl = new StationControl(station, points[i], Properties.Resources.station, size);
				stationDictionary.Add(station, points[i]);
				((ISupportInitialize)stationControl).EndInit();
				Stations.Add(station, stationControl);
				MainControlPanel.Controls.Add(stationControl);
			}
			return stationDictionary;
		}

		private void PaintRoad(List<Agency> roads, Dictionary<Station, Point> stations) {
			int width = MainControlPanel.Width;
			int height = MainControlPanel.Height;
			int size = Math.Min(width, height) / 8;
			Dictionary<int, Station> keyStation = stations.Keys.ToDictionary(each => each.UniqueId, each => each);
			foreach (var agency in roads) {
				if (agency is Road road) {
					Station last = keyStation[road.LastStationId];
					Station next = keyStation[road.NextStationId];
					RoadControl roadControl = new RoadControl(road, stations[last], stations[next], size);
					Roads.Add(road, roadControl);
					MainControlPanel.Controls.Add(roadControl);
				}
			}
		}

		private List<Point> GetPoints(Point center, int axisLength, int count) {
			List<Point> points = new List<Point>();
			double angle = 2 * Math.PI / count;
			double eachAngle = Math.PI;
			for (int i = 0; i < count; i++) {
				int width = Convert.ToInt32(axisLength * Math.Sin(eachAngle));
				int height = Convert.ToInt32(axisLength * Math.Cos(eachAngle));
				points.Add(new Point(center.X + width, center.Y + height));
				eachAngle += angle;
			}
			return points;
		}

		protected override void OnResize(EventArgs eventargs) {
			base.OnResize(eventargs);
			PaintItems();
		}

        private void MainControlPanel_DoubleClick(object sender, EventArgs e) {
			if (OnNetworkClick != null) OnNetworkClick(network);
		}

    }
}
